/* gcc -fPIC -c -O3 -Wall parser.c && gcc -shared -Wl -o parser.so parser.o */

#include "../NewSyndrome-module.h"
#include "../NewSyndrome-base.h"
#include "parser.h"

char *ex_buffer = NULL;

int
parse_argu (msg * irc, char *buffer)
{
  char *runner = buffer;
  unsigned int cc = 0, n;
  irc->argu = (char **) malloc (sizeof (char *));

  while (*buffer != 0)
    {
      for (; *buffer != ' ' && *buffer; buffer++);
      n = buffer - runner;
      irc->argu = (char **) realloc (irc->argu, (cc + 1) * sizeof (char *));
      *(irc->argu + cc) = (char *) malloc (n + 1);

      strncpy (*(irc->argu + cc), runner, n);
      *(irc->argu[cc] + n) = 0;
      cc++;

      while (*buffer == ' ')
	buffer++;
      runner = buffer;
    }
  return cc;
}

#ifdef WIN32
void
init_dep (char *nom, void *addr)
{
  init_share_dep (nom, addr);
}
#endif

void
identify (msg * irc, char *buffer)
{
  char *br;
  unsigned int n;

  for (br = buffer; *br != '!' && *br; br++);
  n = br - buffer;
  irc->sender_nick = (char *) malloc (n + 1);
  strncpy (irc->sender_nick, buffer, n);
  *(irc->sender_nick + n) = 0;
  if (!(*br))
    return;

  for (buffer = ++br; *br != '@' && *br; br++);
  n = br - buffer;
  irc->sender_ident = (char *) malloc (n + 1);
  strncpy (irc->sender_ident, buffer, n);
  *(irc->sender_ident + n) = 0;
  if (!(*br))
    return;

  irc->sender_host = (char *) malloc (strlen (++br) + 1);
  strcpy (irc->sender_host, br);
}

void
parse_header (msg * irc, char *runner)
{
  int ct, i;
  byte point, youp;
  char *plot;

  irc->raw_txt = NULL;
	
  if (*runner == ':')
    {
      for (youp = 0, plot = runner, runner++;  *runner != 0 && youp < 3; runner++)
	if (*runner == ' ')
	  youp++;

      if (*runner == ':')
	*runner++ = 0;
      else if (*runner)
	*(runner - 1) = 0;

      irc->sender_nick = NULL;
      irc->sender_ident = NULL;
      irc->sender_host = NULL;
      irc->cmd = NULL;
      irc->dest = NULL;
      irc->sender = NULL;

      ct = parse_argu (irc, ++plot);	/* header */

      if (ct > 0)
	{
	  irc->sender = (char *) malloc (strlen (irc->argu[0]) + 1);
	  strcpy (irc->sender, irc->argu[0]);

	  identify (irc, irc->sender);
	}
      else
	{
	  irc->sender = (char *) malloc (1);
	  *irc->sender = 0;
	}
      if (ct > 1)
	{
	  irc->cmd = (char *) malloc (strlen (irc->argu[1]) + 1);
	  strcpy (irc->cmd, irc->argu[1]);
	}
      else
	{
	  irc->cmd = (char *) malloc (1);
	  *irc->cmd = 0;
	}
      if (ct > 2)
	{
	  irc->dest = (char *) malloc (strlen (irc->argu[2]) + 1);
	  if (*irc->argu[2] == ':')
	    {
	      if (!strcasecmp (irc->cmd, "QUIT"))
		{
		  *(runner - 1) = ' ';
		  runner -= strlen (irc->argu[2]);
		  free (irc->dest);
		  irc->dest = (char *) malloc (1);
		  *irc->dest = 0;
		}
	      else
		strcpy (irc->dest, (irc->argu[2] + 1));
	    }
	  else
	    strcpy (irc->dest, irc->argu[2]);
	}
      else
	{
	  irc->dest = (char *) malloc (1);
	  *irc->dest = 0;
	}

      for (i = 0; i < ct; i++)
	free (irc->argu[i]);
      free (irc->argu);

      /* ici le pointeur de texte */
      ct = parse_argu (irc, runner);	/* texte */
      irc->raw_txt = runner;
      irc->nbarg = ct;
      
      if (irc->cmd)
	  compar ();

      for (i = 0; i < ct; i++)
	  free (irc->argu[i]);

      free (irc->argu);

      if (irc->cmd != NULL)
	free (irc->cmd);
      if (irc->dest != NULL)
	free (irc->dest);
      if (irc->sender != NULL)
	free (irc->sender);
      if (irc->sender_nick != NULL)
	free (irc->sender_nick);
      if (irc->sender_ident != NULL)
	free (irc->sender_ident);
      if (irc->sender_host != NULL)
	free (irc->sender_host);
    }
  else
    {
      for (plot = runner, runner++; *runner != ':' && *runner; runner++);
      if (*runner == ':')
	point = 1;
      else
	point = 0;

      *runner++ = 0;

      ct = parse_argu (irc, plot);

      irc->cmd = NULL;

      if (ct >= 1)
	{
	  irc->cmd = (char *) malloc (strlen (irc->argu[0]) + 1);
	  strcpy (irc->cmd, irc->argu[0]);
	}
      for (i = 0; i < ct; i++)
	free (irc->argu[i]);
      free (irc->argu);

      if (point)
	{
	  /* pointeur de texte ici */
	  ct = parse_argu (irc, runner);
	  irc->raw_txt = runner;
	  irc->nbarg = ct;
	}
      else
	irc->nbarg = 0;

      irc->sender_nick = (char *) malloc (1);
      *irc->sender_nick = 0;
      irc->sender_host = (char *) malloc (1);
      *irc->sender_host = 0;
      irc->sender_ident = (char *) malloc (1);
      *irc->sender_ident = 0;
      irc->sender = (char *) malloc (1);
      *irc->sender = 0;
      irc->dest = (char *) malloc (1);
      *irc->dest = 0;


      if (irc->cmd != NULL)
	compar ();

      if (point)
	{
	  for (i = 0; i < ct; i++)
	    free (irc->argu[i]);
	  free (irc->argu);
	}
      if (irc->cmd != NULL)
	free (irc->cmd);
      free (irc->dest);
      free (irc->sender);
      free (irc->sender_nick);
      free (irc->sender_host);
      free (irc->sender_ident);
    }
}

char *
expand_buffer_start (char *buffer)
{
  char *run;
  int len;
  for (run = buffer; *run && *run != '\n'; run++);
  if (*run == '\n')
    run++;
  len = (run - buffer) + strlen (ex_buffer);
  ex_buffer = (char *) realloc (ex_buffer, len + 1);
  strncat (ex_buffer, buffer, (run - buffer));
  ex_buffer[len] = 0;
  return run;
}

char *
expand_buffer_end (char *buffer, int len)
{
  char *run;
  for (run = buffer + len; *run != '\n' && run != buffer; run--);
  if (*run == '\n')
    run++;
  ex_buffer = (char *) malloc ((buffer + len) - run + 1);
  strcpy (ex_buffer, run);
  return run;
}

void
parse_buffer (msg * irc, char *buffer)
{
  char *runner = buffer, *tmp;
  int len = strlen (buffer);

  if (ex_buffer == NULL)
    {
      if (buffer[len - 1] != '\n')
	{
	  tmp = expand_buffer_end (buffer, len);
	  *tmp = 0;
	}
    }
  else
    {
      tmp = expand_buffer_start (buffer);
      buffer = tmp;
      if (ex_buffer[strlen (ex_buffer) - 1] == '\n')
	{
	  clean_txt (ex_buffer);
	  parse_header (irc, ex_buffer);
	  free (ex_buffer);
	  ex_buffer = NULL;
	  len = strlen (buffer);
	  if (buffer[len - 1] != '\n')
	    {
	      tmp = expand_buffer_end (buffer, len);
	      *tmp = 0;
	    }

	}
    }

  while (*buffer)
    {
      runner = buffer;
      for (; *buffer != '\n' && *buffer; buffer++);
      if (!(*buffer))
	break;
      if (*buffer == '\n')
	*buffer++ = 0;

      clean_txt (runner);
      parse_header (irc, runner);
    }
}
